package top.cardone.cloud.dubbo.rpc.filter;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.rpc.*;
import top.cardone.context.ApplicationContextHolder;
import top.cardone.core.util.action.Action3;
import top.cardone.core.util.func.Func2;

@Activate(group = {CommonConstants.CONSUMER, CommonConstants.PROVIDER})
public class ActionFilter implements Filter, Filter.Listener {
    String dubboRpcInvokeFuncBeanName = "dubboRpcInvokeFunc";
    String dubboRpcOnResponseActionBeanName = "dubboRpcOnResponseAction";
    String dubboRpcOnErrorActionBeanName = "dubboRpcOnErrorAction";

    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        if(ApplicationContextHolder.getApplicationContext() == null){
            return invoker.invoke(invocation);
        }

        if (!ArrayUtils.contains(ApplicationContextHolder.getApplicationContext().getBeanNamesForType(Func2.class), dubboRpcInvokeFuncBeanName)) {
            return invoker.invoke(invocation);
        }

        Func2<Result, Invoker<?>, Invocation> dubboRpcInvokeFunc = ApplicationContextHolder.getBean(Func2.class, dubboRpcInvokeFuncBeanName);

        if (dubboRpcInvokeFunc == null) {
            return invoker.invoke(invocation);
        }

        return dubboRpcInvokeFunc.func(invoker, invocation);
    }

    @Override
    public void onResponse(Result appResponse, Invoker<?> invoker, Invocation invocation) {
        if(ApplicationContextHolder.getApplicationContext() == null){
            return;
        }

        if (!ArrayUtils.contains(ApplicationContextHolder.getApplicationContext().getBeanNamesForType(Action3.class), dubboRpcOnResponseActionBeanName)) {
            return;
        }

        Action3<Result, Invoker<?>, Invocation> dubboRpcOnResponseAction = ApplicationContextHolder.getBean(Action3.class, dubboRpcOnResponseActionBeanName);

        if (dubboRpcOnResponseAction == null) {
            return;
        }

        dubboRpcOnResponseAction.action(appResponse, invoker, invocation);
    }

    @Override
    public void onError(Throwable t, Invoker<?> invoker, Invocation invocation) {
        if(ApplicationContextHolder.getApplicationContext() == null){
            return;
        }

        if (!ArrayUtils.contains(ApplicationContextHolder.getApplicationContext().getBeanNamesForType(Action3.class), dubboRpcOnErrorActionBeanName)) {
            return;
        }

        Action3<Throwable, Invoker<?>, Invocation> dubboRpcOnErrorAction = ApplicationContextHolder.getBean(Action3.class, dubboRpcOnErrorActionBeanName);

        if (dubboRpcOnErrorAction == null) {
            return;
        }

        dubboRpcOnErrorAction.action(t, invoker, invocation);
    }
}
